package com.example.powernodemall.config;

import com.example.powernodemall.ProjectEnum.ResultEnum;
import com.example.powernodemall.constant.BaseConstant;
import com.example.powernodemall.filter.TokenFilter;
import com.example.powernodemall.model.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.function.Supplier;

@Configuration
public class security_config {
    @Resource
    TokenFilter tokenFilter;
    @Resource
    ObjectMapper objectMapper;
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf(AbstractHttpConfigurer::disable);
        http.cors(AbstractHttpConfigurer::disable);
        http.sessionManagement(httpSecuritySessionManagementConfigurer -> httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
        http.addFilterAfter(tokenFilter, UsernamePasswordAuthenticationFilter.class);
        http.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry.anyRequest().authenticated());
        http.exceptionHandling(exception -> {
            exception.authenticationEntryPoint(authenticationEntryPoint());
            exception.accessDeniedHandler(accessDeniedHandler());
        });
        return http.build();
    }
    @Bean
    public AuthenticationEntryPoint authenticationEntryPoint() {
        return new AuthenticationEntryPoint() {
            @Override
            public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
                response_writer(BaseConstant.ContentJson,response,()-> Result.Failure(ResultEnum.PROHIBIT_LOGiN));
            }
        };
    }
    @Bean
    public AccessDeniedHandler accessDeniedHandler(){
        return new AccessDeniedHandler() {
            @Override
            public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
                response_writer(BaseConstant.ContentJson,response,()-> Result.Failure(ResultEnum.NO_AUTHORIZATION));
            }
        };
    }
    private <T> void response_writer(String contentType, HttpServletResponse response, Supplier<T> supplier) throws IOException {
        response.setContentType(contentType);
        response.setCharacterEncoding(BaseConstant.UTF_8);
        T result = supplier.get();
        PrintWriter writer = response.getWriter();
        writer.write(objectMapper.writeValueAsString(result));
        writer.flush();
        writer.close();
    }
}
